package product

import (
	"context"
	"energy-amiot-platform/core"
	"energy-amiot-platform/model/dbspo"
	"energy-amiot-platform/model/request"
	"energy-amiot-platform/model/response"
	"energy-amiot-platform/repository"
	"energy-amiot-platform/utils/respout"
	"errors"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/jinzhu/copier"
	"gorm.io/gorm"
)

// @Tags 产品管理
// @Summary 添加一个产品
// @Description 添加一个产品
// @Accept  json
// @Product json
// @Param   input 	body 	 request.ProductAddReq  true "产品添加数据"
// @Success 200 	{object} response.Response{result=dbspo.Product} "Ok"
// @Router /product [post]
func create(ctx *gin.Context) {
	var handleCode = 1
	var req request.ProductAddReq
	err := ctx.BindJSON(&req)
	if err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 0, respout.StrErrParse, err, nil)
		return
	}

	db := core.DATABASE.Cur()
	db.Transaction(func(tx *gorm.DB) error {
		t, b := repository.PRODUCT.ExistWithName(tx, req.Name)
		switch {
		case t.Error != nil:
			respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 1, respout.StrFail, t.Error, nil)
			return t.Error
		case b == true:
			respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 2, respout.StrFail, errors.New("产品已存在"), nil)
			return t.Error
		}

		var dpo dbspo.Product
		var masterKey = strings.Replace(uuid.New().String(), "-", "", -1)
		copier.Copy(&dpo, &req)
		dpo.Cid = req.CompanyId
		dpo.MasterKey = masterKey
		err = t.Create(&dpo).Error
		if err != nil {
			respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 3, respout.StrFail, err, nil)
			return err
		}

		respout.Ok(ctx, &dpo)
		return nil
	})
}

// @Tags 产品管理
// @Summary 添加一个产品
// @Description 添加一个产品
// @Product json
// @Param   companyId query int true		"企业标识"
// @Param   name query string false			"产品名称"
// @Param   pageSize query int false		"每页数量" 	default(10)
// @Param   pageNum query int false			"第几页"		default(1)
// @Success 200 {object} response.Response{result=response.PageData{list=dbspo.Product}} "Ok"
// @Router /product [get]
func pagingQuery(ctx *gin.Context) {
	var handleCode = 2
	var req request.ProductPagingQueryReq
	err := ctx.ShouldBindQuery(&req)
	if err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 0, respout.StrErrParse, err, nil)
		return
	}

	switch {
	case req.PageSize == 0:
		req.PageSize = 10
	case req.PageNum == 0:
		req.PageNum = 1
	}

	var count int64
	var result []dbspo.Product
	db := core.DATABASE.Cur()
	if err = db.Model(&dbspo.Product{}).Where("name like ?", "%"+req.Name+"%").Count(&count).Error; err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 1, respout.StrFail, err, nil)
		return
	}

	offset := req.PageSize * (req.PageNum - 1)
	err = db.Model(&dbspo.Product{}).Where("name like ?", "%"+req.Name+"%").Offset(offset).Limit(req.PageSize).Scan(&result).Error
	if err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 2, respout.StrFail, err, nil)
		return
	}

	respout.Ok(ctx, response.PageData{
		Total: count,
		List:  result,
	})
}

// @Tags 产品管理
// @Summary 获取指定标识的产品
// @Description 获取指定标识的产品
// @Product json
// @Param   id 		path 	int 	true		"产品标识"
// @Success 200 {object} response.Response{result=dbspo.Product} "Ok"
// @Router /product/{id} [get]
func findByKey(ctx *gin.Context) {
	var handleCode = 3
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
	if err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 0, respout.StrErrParse, err, nil)
		return
	}

	var result dbspo.Product
	err = core.DATABASE.Cur().First(&result, "id=?", id).Error
	switch {
	case err == gorm.ErrRecordNotFound:
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 1, respout.StrFail, respout.ErrRecordNotFound, nil)
		return
	case err != nil:
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 2, respout.StrFail, err, nil)
		return
	}

	respout.Ok(ctx, result)
}

// @Tags 产品管理
// @Summary 删除产品
// @Description 删除产品
// @Product json
// @Param 	id 		path 	string 	true 		"产品标识"
// @Success 200 {object} response.Response 		"Ok"
// @Router /product/{id} [delete]
func deleteByKey(ctx *gin.Context) {
	var handleCode = 4
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
	if err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 0, respout.StrErrParse, err, nil)
		return
	}

	err = core.DATABASE.Cur().Transaction(func(tx *gorm.DB) error {
		var count int64
		err1 := tx.Raw("select count(1) from ht_device where cid=?", id).Count(&count).Error
		switch {
		case err1 != nil:
			return err1
		case count > 0:
			err2 := errors.New("该产品下有设备")
			return err2
		}

		tx1 := tx.Model(&dbspo.Product{}).Delete("id=?", id)
		switch {
		case tx1.Error != nil:
			return tx1.Error
		case tx1.RowsAffected == 0:
			err2 := errors.New("指定产品不存在")
			return err2
		}

		pipeline := core.REDIS.Pipeline()
		background := context.Background()
		pipeline.Del(background, "mqtt_pdt_sub:"+ctx.Param("id"))
		_, err = pipeline.Exec(background)
		if err != nil {
			return err
		}

		respout.Ok(ctx, nil)
		return nil
	})

	if err != nil {
		respout.SendError(ctx, core.APP.Code, moduleCode, handleCode, 1, respout.StrFail, err, nil)
	}
}
